#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

static int CAS(int *ptr, int oldVal, int newVal)
{
    unsigned char ret;
    __asm__ __volatile__ (
            "  lock\n"
            "  cmpxchgl %2,%1\n"
            "  sete %0\n"
            : "=q" (ret), "=m" (*ptr)
            : "r" (newVal), "m" (*ptr), "a" (oldVal)
            : "memory");

    //above assembly returns 0 in case of failure
    if (ret) return 0;
    return 1;
}

static int lock = 0;
static int counter = 0;
static int dispatch = 0;
void* increment_counter (void* tid)
{
   while(!dispatch);

   int i=0;
   for (;i<10000;i++)
   {
      while(CAS(&lock, 0, 1));
      // only allow one thread to increment at a time
      ++counter;
      // store value before any other threads increment it further
      lock = 0;
   }
}

int main(int argc, char **argv)
{
   pthread_t threads[1024];
   int t_num = atoi(argv[1]);
   void *status;
   
   int i=0;
   for(;i<t_num;i++)
   {
      int rc = pthread_create(&threads[i], NULL, increment_counter, (void *)&i);
   }

   dispatch = 1;

   for(i=0; i<t_num; i++) 
   {
      int rc = pthread_join(threads[i], &status);
   }
  
   printf("end value for counter is %d\n", counter);
   return 0;
}
